// 函数作为返回值

function makerFn() {
  let msg = 'hello makerFn'
  return function () {
    console.log(msg)
  }
}

const fn = makerFn() // fn 接收到一个方法
fn() // 这里再调用 hello makerFn

// makerFn()() // 同上


// once 只执行一次的函数
function once(fn) {
  let done = false
  return  function () {
    if (!done) {
      done = true
      fn.apply(this, arguments) // arguments 是数组形式 所以可直接传递
    //  fn(...arguments) //都可
    }
  }
}

let pay = once((moeny) => { console.log(`支付了${moeny}`) })

pay(5) // 支付了5 只打印一次
pay(5)
pay(5)
pay(5)


// ** 补充 call apply bind 区别

const obj = {
  name: 'tep',
  age: 24,
  say:  function (job, hobby) { 
    console.log(`name: ${this.name}, age: ${this.age} , 职位：${job || '保密'}, 爱好：${hobby || '保密'}`)
  }
}

obj.say('猿', '搬砖'); //name: tep, age: 24 , 职位：猿, 爱好：搬砖

const zs = {
  name: 'zhangsan',
  age: 18,
}




/**
 * name: zhangsan, age: 18 , 职位：教师, 爱好：看书
 * 第一个参数 都是更改this指向
 * 第二个参数开始不相同
 * apply 为数组的形式 call和bind 参数是直接传入的 以逗号隔开
 * 特别注意的是 bind 返回的是一个函数 需要再调用一次
 */

// 注意不能 写 obj.say().apply(zs) 这样就变成了直接调用 报错
obj.say.apply(zs, ['教师', '看书']) // 
obj.say.call(zs, '教师', '看书') // 
obj.say.bind(zs, '教师', '看书')() // 返回一个函数 再次调用